<script setup>
import { computed, ref } from 'vue'
import FileUpload from '@/components/FileUpload/index.vue'

const props = defineProps({
  fieldList: {
    type: Array,
    required: true,
  },
  model: {
    type: Object,
    default: () => ({}),
  },
  options: {
    type: Object,
    default: () => ({}),
  },
})
const emit = defineEmits(['submit', 'cancel'])

// 表单的数据
const model = ref({})
const formRef = ref()

// 设置option默认值，如果传入自定义的配置则合并option配置项
const _options = computed(() => {
  const option = {
    labelPosition: 'right',
    disabled: false,
    submitButtonText: '提交',
    resetButtonText: '重置',
    cancelButtonText: '取消',
    showCancelButton: true,
    footerAlign: 'right',
    footerClass: '',
  }
  return Object.assign(option, props?.options)
})

defineExpose({
  formRef,
})

watch(
  () => props.model,
  () => {
    props.fieldList.forEach((item) => {
      const value = item.type === 'checkbox' ? [] : ''
      if (props.model) {
        model.value = props.model
      }
      else {
        model.value[item.field] = item.value || value
      }
    })
  },
  { immediate: true },
)

// 提交按钮
function onSubmit(formEl) {
  if (!formEl) {
    return
  }
  formEl.validate((valid) => {
    if (valid) {
      emit('submit', model.value)
    }
    else {
      return false
    }
  }, 500)
}

// 输入框回车事件
function handleKeyUp(enterable) {
  if (!enterable) {
    return
  }
  onSubmit(formRef.value)
}

// 重置
function resetForm(formEl) {
  if (!formEl) {
    return
  }
  formEl.resetFields()
}

function debounce(callback, wait, options) {
  let timeoutId

  return function (...args) {
    const context = this

    const later = () => {
      timeoutId = null
      if (!options || (options && !options.leading)) {
        callback.apply(context, args)
      }
    }

    const callNow = options && !timeoutId && !options.trailing

    clearTimeout(timeoutId)
    timeoutId = setTimeout(later, wait)

    if (callNow) {
      callback.apply(context, args)
    }
  }
}
function handleCascaderProps(props) {
  return props
}
function handleCascaderChange(val) {

}
</script>

<template>
  <el-form v-bind="_options" ref="formRef" :model="model" :label-width="_options.labelWidth || '80px'" @submit.prevent>
    <el-row :gutter="_options.gutter || 20">
      <template v-for="(item, index) in fieldList" :key="index">
        <el-col v-if="item.type === 'radio'" :span="item.span || 12">
          <!-- 单选框 -->
          <el-form-item :label="item.label" :rules="item.rules" :prop="[item.field]" :class="item.labelClass || 'custom-base-form-label'">
            <el-radio-group v-model="model[item.field]" :disabled="item.disabled">
              <el-radio
                v-for="val in item.options?.data"
                :key="val[item.options?.valueKey || 'value']"
                :value="val[item.options?.valueKey || 'value']"
              >
                {{ val[item.options?.labelkey || 'label'] }}
              </el-radio>
            </el-radio-group>
          </el-form-item>
        </el-col>
        <el-col v-else-if="item.type === 'checkbox'" :span="item.span || 12">
          <!-- 复选框 -->
          <el-form-item
            :label="item.label"
            :rules="item.rules"
            :prop="[item.field]"
          >
            <el-checkbox-group v-model="model[item.field]" :disabled="item.disabled">
              <el-checkbox
                v-for="c in item.options?.data"
                :key="c[item.options?.valueKey || 'value']"
                :label="c[item.options?.valueKey || 'value']"
              >
                {{ c[item.options?.labelkey || 'label'] }}
              </el-checkbox>
            </el-checkbox-group>
          </el-form-item>
        </el-col>
        <!-- 下拉框 -->
        <el-col v-else-if="item.type === 'select'" :span="item.span || 12">
          <el-form-item
            :label="item.label"
            :rules="item.rules"
            :prop="[item.field]"
            :class="item.labelClass || 'custom-base-form-label'"
          >
            <el-select
              v-model="model[item.field]" :placeholder="item.options?.placeholder || `请选择${item.label}`"
              :clearable="item.clearable || true"
              :disabled="item.disabled"
            >
              <el-option
                v-for="s in item.options?.data"
                :key="s[item.options?.value || 'value']"
                :label="s[item.options?.label || 'label']"
                :value="s[item.options?.value || 'value']"
              />
            </el-select>
          </el-form-item>
        </el-col>

        <!-- 时间选择器 -->
        <el-col v-else-if="item.type === 'date'" :span="item.span || 12">
          <el-form-item
            :label="item.label"
            :rules="item.rules"
            :prop="[item.field]"
            :class="item.labelClass || 'custom-base-form-label'"
          >
            <el-date-picker
              v-model="model[item.field]"
              type="date"
              :placeholder="item.placeholder || `请选择${item.label}`"
              :disabled="item.disabled"
              class="!w-full"
              :value-format="item.valueFormat || 'YYYY-MM-DD hh:mm:ss'"
            />
          </el-form-item>
        </el-col>
        <!-- 时间范围选择器 -->
        <el-col v-else-if="item.type === 'daterange'" :span="item.span || 12">
          <el-form-item
            :label="item.label"
            :rules="item.rules"
            :prop="[item.field]"
            :class="item.labelClass || 'custom-base-form-label'"
          >
            <el-date-picker
              v-model="model[item.field]"
              type="daterange"
              range-separator="至"
              start-placeholder="开始日期"
              end-placeholder="结束日期"
              :disabled="item.disabled"
              class="w-full"
              :value-format="item.valueFormat || 'YYYY-MM-DD hh:mm:ss'"
            />
          </el-form-item>
        </el-col>
        <!--        级联 -->
        <el-col v-else-if="item.type === 'cascader'" :span="item.span || 12">
          <el-form-item
            :label="item.label"
            :rules="item.rules"
            :prop="[item.field]"
            :class="item.labelClass || 'custom-base-form-label'"
          >
            <el-cascader
              v-model="model[item.field]"
              :options="item.options?.data"
              :props="handleCascaderProps(item.props)"
              :disabled="item.disabled"
              class="w-full"
              filterable
              @change="handleCascaderChange"
            />
          </el-form-item>
        </el-col>
        <el-col v-else-if="item.type === 'switch'" :span="item.span || 12">
          <!-- 开关 -->
          <el-form-item
            :label="item.label"
            :rules="item.rules"
            :prop="[item.field]"
          >
            <el-switch
              v-model="model[item.field]" :disabled="item.disabled"
              :active-text="options.switchActiveText || '开启'"
              :inactive-text="options.switchInactiveText || '关闭'"
              :active-value="options.switchActiveValue || true"
              :inactive-value="options.switchInactiveValue || false"
              :inline-prompt="options.switchInlinePrompt || false"
            />
          </el-form-item>
        </el-col>
        <el-col v-else-if="item.type === 'upload'" :span="item.span || 12">
          <!-- 上传 -->
          <el-form-item
            :label="item.label"
            :rules="item.rules"
            :prop="[item.field]"
            :class="item.labelClass || 'custom-base-form-label'"
            :label-width="item.labelWidth || ''"
          >
            <FileUpload
              v-model="model[item.field]"
              :limit="item.limit || 100"
              :file-type="item.fileType || ['doc', 'xls', 'ppt', 'txt', 'pdf']"
              :is-show-tip="item.isShowTip || true"
              class="w-full"
              :tips="item.tips || '' "
            />
          </el-form-item>
        </el-col>
        <!--        自定义 -->
        <el-col v-else-if="item.type === 'custom'" :span="item.span || 12">
          <el-form-item :label="item.label" :rules="item.rules" :prop="[item.field]" :class="item.labelClass || 'custom-base-form-label'">
            <slot :name="item.slotName" :item="item" />
          </el-form-item>
        </el-col>
        <!-- 默认输入框 -->
        <el-col v-else :span="item.span || 12">
          <el-form-item
            :label="item.label" :rules="item.rules" :prop="[item.field]" :class="item.labelClass || 'custom-base-form-label'"
            :title="item.title || ''"
            :label-width="item.labelWidth || ''"
          >
            <el-input
              v-model="model[item.field]"
              :readonly="item.readonly"
              :type="item.type ?? 'text'"
              :placeholder="item.placeholder || `请输入${item.label}`"
              :disabled="item.disabled"
              :show-password="item.showPassword"
              :clearable="item.clearable || true"
              :maxlength="item.maxlength"
              :show-word-limit="item.maxlength ? true : false"
              @keyup.enter="handleKeyUp(item.enterable)"
            >
              <template v-if="item.suffix" #suffix>
                {{ item.suffix }}
              </template>
            </el-input>
          </el-form-item>
        </el-col>
      </template>
    </el-row>

    <div
      class="flex mt-5"
      :class="[
        { 'justify-end': _options.footerAlign === 'right' },
        { 'justify-center': _options.footerAlign === 'center' },
        { 'justify-start': _options.footerAlign === 'left' },
        _options.footerClass,
      ]"
    >
      <slot name="buttons" :model="model" :form-ref="formRef">
        <el-button type="primary" class="w-20 mr-1" @click="debounce(onSubmit(formRef), 500)">
          {{ _options.submitButtonText }}
          <el-icon class="ml-1">
            <SuccessFilled />
          </el-icon>
        </el-button>
        <el-button v-if="_options.showResetButton" type="info" @click="resetForm(formRef)">
          {{ _options.resetButtonText }}
        </el-button>
        <el-button v-if="_options.showCancelButton" class="w-20" plain type="primary" @click="emit('cancel')">
          {{ _options.cancelButtonText }}
          <el-icon class="ml-1">
            <CircleCloseFilled />
          </el-icon>
        </el-button>
      </slot>
    </div>
  </el-form>
</template>

<style scoped lang="scss">
:deep(.custom-base-form-label){
    .el-form-item__label{
      display: block;
      white-space:nowrap;
      overflow:hidden;
      text-overflow:ellipsis;
      text-align: right;
    }
}
</style>
